#include <stm32_def.h>
#include "usbstick.h"
#include "usb_host.h"
#include "usbh_core.h"
#include "usbh_diskio.h"

#ifdef USE_FATFS

#include "fatfs.h"
#include "core_debug.h"

FATFS USBHFatFS; /* File system object for USBH logical drive */
FIL USBHFile;    /* File object for USBH */
#endif
#ifdef USB_HOST_HS
USBH_HandleTypeDef hUsbHostHS;
#endif
extern USBH_HandleTypeDef hUsbHostFS;

uint8_t retUSBH;  /* Return value for USBH */
char USBHPath[4]; /* USBH logical drive path */

extern "C"
{
void MX_USB_HOST_Process(void);
USBH_StatusTypeDef USBH_Start(USBH_HandleTypeDef *phost);
//void _Error_Handler(const char *, int) {} ;
//void Error_Handler();
}

void USBStick::begin() {
#ifdef USE_FATFS
    retUSBH = FATFS_LinkDriver(&USBH_Driver, USBHPath);
#endif
    MX_USB_HOST_Init();
}

int USBStick::loop() {
    MX_USB_HOST_Process();

    return 0;
}

int USBStick::mount() {
#ifdef USE_FATFS
    int res = f_mount(&USBHFatFS, "", 0);
    if (FR_OK != res) {
        Error_Handler();
    } else {
        core_debug("mount sucess !!! \r \n");
    }
    return res;
#endif
}

int USBStick::isConnected() {
    return hUsbHostFS.gState;
}

void USBStick::stop() {
    if (USBH_Stop(&hUsbHostFS) != USBH_OK) {
        Error_Handler();
    }
}

#ifdef USE_FATFS

int USBStick::open_file(const char *filename) {
    int res;
    res = f_open(&USBHFile, filename, FA_CREATE_ALWAYS | FA_WRITE);
    if (res)
        core_debug("open file %s error ：%d\n", filename, res);
    else {
        core_debug("open file sucess !!! \r \n");
    }
    return res;
}

int USBStick::write(const char *wtext, int len) {
    unsigned int byteswritten;
    int res;
    res = f_write(&USBHFile, wtext, len, (unsigned int *) &byteswritten);
    if (res)
        core_debug("file write error: %d \r \n", res);
    else {
        core_debug("write file sucess %d= %d!!! \r \n", len, byteswritten);
    }
    return res;
}

int USBStick::close() {
    int res;
    res = f_close(&USBHFile);
    if (res)
        core_debug("close file error:%d \r \n", res);
    else {
        core_debug("close sucess.  \r \n");
    }
    return res;
}

int USBStick::open_file_rdonly(const char *filename) {
    int res;
    res = f_open(&USBHFile, filename, FA_READ);
    if (res)
        core_debug("open file %s error : %d \r \n", filename, res);
    else {
        core_debug("open file ok. \r \n");
    }
    return res;
}

int USBStick::read(char *rtext, int len) {
    int bytesread;
    int res;
    res = f_read(&USBHFile, rtext, len, (unsigned int *) &bytesread);
    if (res)
        core_debug("read error !!!%d \r \n", res);
    else {
        core_debug("read sucess :%d !!! \r \n", bytesread);
    }
    return bytesread;
}

int USBStick::stat(const char *filename) {
    int res;
    FILINFO info;
    fsize = -1;
    res = f_stat(filename, &info);
    if (res)
        core_debug("stat error%d \r \n", res);
    else {
        core_debug("stat ok. \r \n");
        fsize = info.fsize;
    }
    return res;
}

bool USBStick::exists(const char *filename) {
    if (stat(filename) == 0 && fsize >= 0)
        return true;
    return false;
}

#endif
#if 0
int USBStick::ls(char *path)
{
    int res;
    FILINFO fno;
    DIR dir;
    int i;
    char *fn; /* This function is assuming non-Unicode cfg. */
#if _USE_LFN
    static char lfn[_MAX_LFN + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof(lfn);
#endif
    core_debug("ls dir=%s\n",path);
    res = f_opendir(&dir, path); /* Open the directory */
    if (res == FR_OK)
    {
        i = strlen(path);
        for (;;)
        {
            res = f_readdir(&dir, &fno); /* Read a directory item */
            if (res != FR_OK || fno.fname[0] == 0)
                break; /* Break on error or end of dir */
            if (fno.fname[0] == '.')
                continue; /* Ignore dot entry */
#if _USE_LFN
            fn = *fno.lfname ? fno.lfname : fno.fname;
#else
            fn = fno.fname;
#endif
            if (fno.fattrib & AM_DIR)
            { /* It is a directory */
                sprintf(path, "/%s", fn);
                res = ls(path);
                if (res != FR_OK)
                    break;
                path = 0;
            }
            else
            { /* It is a file. */
                core_debug("%s/%s\n", path, fn);
            }
        }
    }

    return res;
}
#endif
USBStick usb;
